#include<stdio.h>
#include<stdlib.h>
#include"matrix.h"


/* Takes as input n vectors in the array named vectors. Returns 1 if they are all
 * linearly independent. Otherwise returns 0.
 * The vectors are linearly dependent if the matrix formed by their components if non-invertible. 
 * i.e. Determinant is 0.
 */
 

/* Reads matrix A */
void read_matrix1(float A[][N], int *ptr_n, int *ptr_m)
{
	printf("Input the size of the matrix: ");
	scanf("%d %d", ptr_n, ptr_m);

	printf("Input the %d x %d matrix:\n", *ptr_n, *ptr_m);
	for (int i = 0; i < *ptr_n; i++)
		for (int j = 0; j < *ptr_m; j++)
			scanf("%f", &A[i][j]);
}

/* Return s transpose in trA */
void transpose(float A[][N], float trA[][N], int *ptr_n, int *ptr_m)
{
	for (int i = 0; i < *ptr_n; i++)
		for (int j = 0; j < *ptr_m; j++)
			trA[j][i]=A[i][j];
}


/* Outputs matrix A */
void output_matrix1(char *statement, float A[][N], int n, int m)
{
	printf(statement);
	for (int i = 0; i < n; i++) { // output i-th row
		for (int j = 0; j < m; j++)
			// output j-th element of i-th row
			printf("%5.2f ", A[i][j]);
		printf("\n");
	}
}

/* Takes a  n*n matrix from position r,c */
void take(float A[][N], float a[][N], int n, int r, int c)
{
	for(int i=0; i<n; i++)
		for(int j=0; j<n; j++)
			a[i][j]=A[i+r][j+c];
}

/* Converts into echelon form*/
void echelon(float A[][N], int n, int m)
{
	for(int i=0 ; i<n ; i++)
	{
		for(int j=i; j<n; j++)
		{
			int r=nonzero_row(A, n, m, i);
			if(r==-1)
				break;
			swap_row(A, n, m, r, i);
			int c=nonzero(A[i], m);
			for(int k=0; k<n; k++)
				if(k!=i)
					add_row(A[k],A[i],-A[k][c]/A[i][c],m);			
		}			
	}
}
/* Finds the rank from echelon matrix*/	
int rank(float A[][N], int n, int m)
{
	int count=0;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(A[i][j]!=0)
			{
				count++;
				break;
			}
	return count;
}	

/* Gives the elements in the basis for the n vectors*/ 
int dim_basis(Vector vectors[], int n)
{
	int basis=1;
        Vector basisvectors[N];


        basisvectors[0]=vectors[0];  
	if(n==1)
		return 1;
	for(int i=1;i<n;i++)
        {        
                // check_vector_basis function will return zero if there is dependency and non zero if they are independent

		if(check_vector_dep(basisvectors,basis,vectors[i]))
		{
                        basisvectors[basis]=vectors[i];
                        basis++;
		}
        }
		
	return basis;
	
	
}


/* Checks for linera dependence of vector u with the n vectors in vectors[]*/
int check_vector_dep(Vector vectors[], int n, Vector u)
{
	int dim=vectors[0].dim;
	
	
	if(n>=dim)
		return 0;
	else if(n==dim-1)
	{
		float A[N][N];
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<vectors[i].dim; j++)
				A[j][i]=vectors[i].elements[j];

		}	
			
		for(int i=0;i<dim;i++)
			A[i][n]=u.elements[i];
		if(determinant(A,n+1))
			return 1;
		else
			return 0;

	}
	if(n<dim-1)
	{        
                Vector vt[N];
                float * array;
                int i,j,tcount; 
                 for(i=0;i<N;i++)
                 {
                      array=(float *)malloc(8*100);
                      vt[i].elements=array;
                 } 
                 
                 for(i=0;i<n;i++)
                 {

                     for(j=0;j<dim;j++)
                     {
                         vt[j].dim=n+1;
                         vt[j].elements[i]=vectors[i].elements[j];
                     }
                 } 
  
                 for(i=0;i<dim;i++)
                 vt[i].elements[n]= u.elements[i];
              
                 if((n+1==dim_basis(vt,dim)))
                 return 1;
                 else
                 return 0;
               
	}

	
		
}		
	

